package model;



/**
 * The RectangularPart class is a {@link RectangularArea} and represents a part of a {@link Window} that is
 * smaller than or of equal size and is inside of that {@link Window}.
 *
 */
public class RectangularPart extends RectangularArea {
	
	private RectangularArea parent;
	
	public RectangularPart(final Point position, final int width, final int height) {
		super(position, width, height);
	}
	@Override
	public String toString(){
		return super.toString() + " { PARENT: " + this.getParent().toString() + " }";
	}
	private RectangularArea getParent() {
		return this.parent;
	}
	void setParent(final RectangularArea parent) throws HierarchyException {
		if (parent.equals(this)) throw new HierarchyException();
		this.parent = parent;
	}
	@Override
	public boolean isIn(final RectangularArea area) {
		if (this.getParent() == null) return false;
		return this.getParent().isIn(area);
	}

	/**
	 * Returns the 0-4 {@link RectangularPart}s that are not obstructed by the provided {@link Window} as {@link RectangularPartCollection}.
	 * @param window is a {@link Window} that is above the parent {@link Window}.
	 * 
	 * @return a {@link RectangularPartCollection} with 0-4 elements.
	 */
	public RectangularPartCollection getNonOverlappingArea(final Window window) {
		final RectangularPartCollection result = new RectangularPartCollection();
		if(window.getTop() >= this.getTop() && window.getTop() <= this.getBottom()){
			result.add(getValidPart(this.getLeftUpperCorner(),this.getWidth(),window.getTop() - this.getTop()));
		}
		if(window.getRight() <= this.getRight() && window.getRight() >= this.getLeft()){
			result.add(getValidPart(new Point(window.getRight(), Math.max(this.getTop(), window.getTop())),
					this.getRight() - window.getRight(), 
					Math.min(this.getBottom(), window.getBottom()) - Math.max(this.getTop(), window.getTop())));
		}
		if(window.getBottom() <= this.getBottom() && window.getBottom() >= this.getTop()){
			result.add(getValidPart(new Point(this.getLeft(), window.getBottom()),
					this.getWidth(),
					this.getBottom() - window.getBottom()));
		}
		if(window.getLeft() >= this.getLeft() && window.getLeft() <= this.getRight()){
			result.add(getValidPart(new Point(this.getLeft(), Math.max(this.getTop(), window.getTop())),
					window.getLeft() - this.getLeft(),
					Math.min(this.getBottom(), window.getBottom()) - Math.max(this.getTop(), window.getTop())));
		}
		return result;
	}
	
	/**
	 * Returns a {@link RectangularPartCollection} containing either a single or no {@link RectangularPart}.
	 * The result only contains a {@link RectangularPart} when the provided width and height are greater than zere and 
	 * therefore valid.
	 * @param leftUpperCorner the left upper corner of the part.
	 * @param width is the width of the part.
	 * @param height is the height of the part.
	 * @return a {@link RectangularPartCollection} containing either a single or no {@link RectangularPart}.
	 */
	private RectangularPartCollection getValidPart(final Point leftUpperCorner, final int width, final int height) {
		final RectangularPartCollection result = new RectangularPartCollection();
		if(height > 0 && width > 0)
			result.add(new RectangularPart(leftUpperCorner,
					width,
					height));
		return result;
	}
	@Override
	public boolean equals(final Object obj) {
		final RectangularPart other = (RectangularPart) obj;
		if(!this.getLeftUpperCorner().equals(other.getLeftUpperCorner())){
			return false;
		}
		if(this.getHeight() != other.getHeight()){
			return false;
		}
		if(this.getWidth() != other.getWidth()){
			return false;
		}
		return true;
	}
}
@SuppressWarnings("serial")
class HierarchyException extends Exception {
	public HierarchyException() {
		super("No cycles!!!");
	}
}